#include "Render/PlaneRenderable.h"

#include <glut.h>

namespace vital {

	//--------------------------------------------------------------------------
	TPlaneRenderable::TPlaneRenderable(
		const TVec2 &size,
		const TVec2 &tile,
		size_t division,
		bool twoSided,
		const TMtx4 &rotation) {

			mTwoSided = twoSided;
			buildPlaneMesh(size, tile, division, rotation);
	}

	//--------------------------------------------------------------------------
	TPlaneRenderable::~TPlaneRenderable() {

	}

	//--------------------------------------------------------------------------
	void TPlaneRenderable::render() {

		glBegin(GL_TRIANGLES);

		glNormal3fv( mNormal.getData() );

		for(size_t row = 0; row < mDivisions; ++row) {

			for(size_t col = 0; col < mDivisions; ++col) {

				Quad &quad = mQuads[row * mDivisions + col];

				glTexCoord2fv( mTexcoords[ quad.idx[0] ].getData() );
				glVertex3fv( mVertices[ quad.idx[0] ].getData() );

				glTexCoord2fv( mTexcoords[ quad.idx[3] ].getData() );
				glVertex3fv( mVertices[ quad.idx[3] ].getData() );

				glTexCoord2fv( mTexcoords[ quad.idx[2] ].getData() );
				glVertex3fv( mVertices[ quad.idx[2] ].getData() );

				glTexCoord2fv( mTexcoords[ quad.idx[0] ].getData() );
				glVertex3fv( mVertices[ quad.idx[0] ].getData() );

				glTexCoord2fv( mTexcoords[ quad.idx[2] ].getData() );
				glVertex3fv( mVertices[ quad.idx[2] ].getData() );

				glTexCoord2fv( mTexcoords[ quad.idx[1] ].getData() );
				glVertex3fv( mVertices[ quad.idx[1] ].getData() );

			}
		}

		if(mTwoSided) {

			glNormal3fv( TVec3(-mNormal).getData() );

			for(size_t row = 0; row < mDivisions; ++row) {

				for(size_t col = 0; col < mDivisions; ++col) {

					Quad &quad = mQuads[row * mDivisions + col];

					glTexCoord2fv( mTexcoords[ quad.idx[1] ].getData() );
					glVertex3fv( mVertices[ quad.idx[1] ].getData() );

					glTexCoord2fv( mTexcoords[ quad.idx[2] ].getData() );
					glVertex3fv( mVertices[ quad.idx[2] ].getData() );

					glTexCoord2fv( mTexcoords[ quad.idx[3] ].getData() );
					glVertex3fv( mVertices[ quad.idx[3] ].getData() );

					glTexCoord2fv( mTexcoords[ quad.idx[1] ].getData() );
					glVertex3fv( mVertices[ quad.idx[1] ].getData() );

					glTexCoord2fv( mTexcoords[ quad.idx[3] ].getData() );
					glVertex3fv( mVertices[ quad.idx[3] ].getData() );

					glTexCoord2fv( mTexcoords[ quad.idx[0] ].getData() );
					glVertex3fv( mVertices[ quad.idx[0] ].getData() );

				}
			}
		}

		glEnd();

	}

	//--------------------------------------------------------------------------
	void TPlaneRenderable::buildPlaneMesh(
		const TVec2 &size,
		const TVec2 &tile,
		size_t division,
		const TMtx4 &rotation) {

			mDivisions = division;

			mVertices.resize( (division + 1) * (division + 1) );
			mTexcoords.resize( (division + 1) * (division + 1) );
			mQuads.resize( division * division );

			const float invDivision = 1.0f / (float)division;
			const float halfWidth = size[0] * 0.5f;
			const float halfHeight = size[1] * 0.5f;

			mNormal = toVec3( rotation * TVec4(0.0f, 0.0f, 1.0f, 0.0f) );

			for(size_t row = 0; row < division + 1; ++row) {

				for(size_t col = 0; col < division + 1; ++col) {

					TVec3 &v = mVertices[row * (division+1) + col];

					v[0] = halfWidth * ( (float)col * invDivision * 2.0f - 1.0f );
					v[1] = halfHeight * ( (float)row * invDivision * 2.0f - 1.0f );
					v[2] = 0.0f;

					v = rotation * v;

					TVec2 &texcoord = mTexcoords[row * (division+1) + col];
					texcoord[0] = tile[0] * (float)col * invDivision;
					texcoord[1] = tile[1] * (float)row * invDivision;
				}
			}

			for(size_t row=0; row < division; ++row) {

				for(size_t col=0; col < division; ++col) {

					Quad &quad = mQuads[row * division + col];

					size_t baseIdx = row * (division+1) + col;

					// 0   1
					//
					// 3   2

					quad.idx[0] = baseIdx + 0;
					quad.idx[1] = baseIdx + 1;

					// next row's index
					baseIdx += (division + 1);

					quad.idx[2] = baseIdx + 1;
					quad.idx[3] = baseIdx + 0;
				}
			}
	}

	//--------------------------------------------------------------------------

}